#include "Basic.h"
#include "Renderer.h"
#include "BasicGeometry.h"

namespace Nezha
{

	void Basic::initialSetConfig(EngineConfig* cfg)
	{
		cfg->mAppName = "Basic";
		cfg->mScreenWidth = 800;
		cfg->mScreenHeight = 600;
		cfg->mWindowPosX = -1;
		cfg->mWindowPosY = -1;
		cfg->mAttachTestSystem = true;
		cfg->mWindowed = true;
		cfg->mColorBufferBits = 32;
		cfg->mInitialPluginNames.push_back("RendererGLES_d");
	}

	void printMatrix()
	{

	}

	static BasicGeometry* s_BG = NULL;

	class CustemCullingAlighedQuad : public CustomCullingProc
	{
	public:
		bool isSceneNodeVisible(SceneNode* sn, RenderTarget* curRT)
		{
			if(sn == mSN && curRT == mRT)
			{
				return true;
			}

			return false;
		}

	public:
		SceneNode* mSN;
		RenderTarget* mRT;
	};

	static CustemCullingAlighedQuad g_AlighedQuadCulling;

	bool Basic::initialize()
	{
		Renderer* r = Renderer::GetGlobal();

		SceneGraph* sg = r->getSceneGraph();

		Camera* cam = sg->getCamera("MainCamera");	
		cam->setPosition(Vector3(0.0f, 2.0f, 5.0f));

		BasicGeometry* box = sg->createBuiltInBox("box");
		sg->getRootNode()->attachChild(static_cast<SceneNode*>(box));

		s_BG = box;

		Light* lit = sg->createLight("DirLight");
		lit->setLightType(LT_DIRECTIONAL);
		lit->mDirection.set(1.0f, -1.0f, -1.0f);
		lit->mDirection.normalize();
		lit->mCastShadow = false;
		lit->mColor = RGBA::WHITE;

		MaterialPtr mat = r->getMaterialManager()->createDefaultMaterial(DST_DIRECTIONAL_SPECULAR);
		box->setMaterial(0, mat);

		// test
		//mat->setFillMode(0, RSFM_WIREFRAME);

		ShaderParameter* u_color = mat->getUserSpecParam(0, "u_color");

		if(u_color)
		{
			u_color->setData<Vector4>(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
		}

		ShaderParameter* u_diffColor = mat->getUserSpecParam(0, "MatDiffuseColor");

		if(u_diffColor)
		{
			u_diffColor->setData<Vector4>(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
		}

		ShaderParameter* u_specColor = mat->getUserSpecParam(0, "MatSpecColor");

		if(u_specColor)
		{
			u_specColor->setData<Vector4>(Vector4(1.0f, 0, 0, 1.0f));
		}

		TextureManager* tm = r->getTextureManager();
		_Image2DPtr img = tm->load2DImage("Nezha.png");


		if(img.notNull())
		{
			TexturePtr tex = tm->create2DTexture(*img.get(), true);
			if(tex.notNull())
			{
				ShaderSampler* ss = mat->_getPass(0)->getSamper(0);
				if(ss)
				{
					_SamplerInfo si;
					si.mSamplerType = SAMPLER_2D;
					si.mTextureID = tex->getID();
					ss->_setSamplerInfo(si);
				}
			}

			img.release();
		}

		// set clear color
		r->getFrameBuffer()->getViewport(0)->mBackColor = RGBA::BLUE;

		box->setPosition(Vector3(1.0f, 0, 0));

		//r->overrideGlobalFillMode(RSFM_IGNORE);

		cam->setDirection(-cam->getPosition());//(-Vector3(2.0f, 0, 10.0f));
		//cam->setFrustum(60.0f, 4.0f / 3.0f, 0.1f, 300.0f);
		//
		//GeometryDataBatch batch;
		//box->prepareGeometry4Pipeline(batch);
		//GeometryData* gd = batch._accessData_BeCarefulOffset();
		//VertexBufferAccessor vba;
		//vba.beginAccess(GeometryDataPtr(gd));
		//const VertexBufferAccessor::VertexElemBinding * veb = vba.getElemBindingByVS(VS_POSITION);
		//u16 numVerts = gd->getNumVertex();

		//Matrix4x4 cvp = cam->getProjectionMat() * cam->getViewMat() * box->getWorldTransform();

		//for(int i = 0; i < numVerts; i++)
		//{
		//	Vector3& v = vba.accessChannel<Vector3>(*veb, i);
		//	Vector4 v4 = cvp * Vector4(v, 1.0f);

		//	v.x = v4.x / v4.w;
		//	v.y = v4.y / v4.w;
		//	v.z = v4.z / v4.w;

		//	printf("pt %d <%f, %f, %f>\n", i, v.x, v.y, v.z);
		//}

		//vba.endAccess();


		//// TEST for RT
		//const int RTDim = 512;
		//RenderTarget* rt = r->getRTTManager()->createRenderTarget(RTDim, RTDim, 0, TF_A8R8G8B8, true);
		//rt->setVisiblityMask(0x2);
		//RectI rc(0, 0, r->getWidth(), r->getHeight());
		//Viewport* vp = rt->addViewport(0, rc);

		//BasicGeometry* quad = sg->createBuiltInPlane("Quad", 1, 1);
		//sg->getRootNode()->attachChild(static_cast<SceneNode*>(quad));
		//quad->setCullingMask(0x2);
		//g_AlighedQuadCulling.mRT = rt;
		//g_AlighedQuadCulling.mSN = static_cast<SceneNode*>(quad);
		//quad->setCustomCulling(static_cast<CustomCullingProc*>(&g_AlighedQuadCulling));

		//MaterialPtr matTex = r->getMaterialManager()->createDefaultMaterial(DST_SINGLE_TEX);
		//quad->setMaterial(0, matTex);

		//Texture* rtex = rt->getRenderTexture(0);
		//if(rtex)
		//{
		//	ShaderSampler* ss = matTex->_getPass(0)->getSamper(0);
		//	if(ss)
		//	{
		//		_SamplerInfo si;
		//		si.mSamplerType = SAMPLER_2D;
		//		si.mTextureID = rtex->getID();
		//		ss->_setSamplerInfo(si);
		//	}
		//}

		return true;
	}

	static float s_CamRotTime = 0;

	bool Basic::externalUpdate()
	{
		Renderer* r = Renderer::GetGlobal();

		Camera* cam = r->getCamera();

		//cam->rotate(Vector3::UNIT_Y, NZ_PI_OVER4 * r->getFrameDelta());

		Quaternion quat(Vector3::UNIT_Y, NZ_PI_OVER4 * r->getFrameDelta());
		s_BG->rotate(quat);

		//// rotate camera
		//float len = cam->getPosition().length();
		//cam->setPosition(Vector3(0, 0, 0));
		//cam->rotate(Vector3::UNIT_Y, -NZ_PI_OVER4 * r->getFrameDelta());
		//cam->setPosition(-cam->getDirection() * len);

		return true;
	}

	void Basic::uninitialize()
	{

	}

	static MiniFrameworkCreatorAutoRegister<Basic> s_BasicCreator("Basic");

}//end namespace Nezha